import xml.dom.minidom
from core.task import Task
from core.node import Node


class BasicParser:
    def __init__(self, filename):
        self.DOMTree = xml.dom.minidom.parse(filename)
        self.collection = self.DOMTree.documentElement


        self.node_list = self._parse_task()
        self.dependencies = self.generate_dependency()
        # self.ids_to_depth = self._calculate_depth()

        # self.sorted_task = self.sort_task_by_EFT()

    def _parse_task(self):
        nodes = self.collection.getElementsByTagName("node")
        node_list = []

        for node in nodes:
            node_id = node.getAttribute("id")
            depth = int(node.getAttribute("depth"))
            singleTask=bool(node.getAttribute("singleTask"))
            sortTask = bool(node.getAttribute("sortTask"))
            # running_time = float(node.getAttribute("runtime"))

            tasks_tag = node.getElementsByTagName("task")
            tasks = []
            for task_tag in tasks_tag:
                task_id = task_tag.getAttribute("id")
                type = task_tag.getAttribute("type")
                task = Task(task_id,type)
                tasks.append(task)
            node_dag = Node(node_id,tasks,depth,sortTask,)
            node_list.append(node_dag)

        return node_list




    def get_node_map(self)->dict:

       return dict([(node.id, node) for node in self.node_list])

    def get_nodes(self):


        return self.node_list

    def generate_dependency(self):
        children = self.collection.getElementsByTagName("child")
        dependencies = {}
        idx_id = dict( [(node.id,idx) for idx,node in enumerate(self.node_list)])

        for child in children:
            child_id = child.getAttribute("ref")
            child_node = self.node_list[idx_id[child_id]]
            parents = child.getElementsByTagName("parent")

            for parent in parents:
                parent_id = parent.getAttribute("ref")
                parent_node = self.node_list[idx_id[parent_id]]
                child_node.set_parent(parent_node)
                parent_node.set_child(child_node)
                dependencies[(parent_id,child_id)] = 1 # 依赖顺序


        return dependencies

    # def sort_task_by_EFT(self):
    #     #sort all task by EFT
    #     heft_rank = {}
    #
    #     def CalculateRankForEach(task_id):
    #         if task_id in heft_rank.keys():
    #             return heft_rank[task_id]
    #         else:
    #             if len(self.succ_task_for_ids[task_id]) != 0:
    #                 score = self.ids_to_task[task_id].running_time + max( [self.dependencies[(task_id, succ_task_id)] +
    #                                               CalculateRankForEach(succ_task_id) for succ_task_id in self.succ_task_for_ids[task_id]])
    #             else:
    #                 score = self.ids_to_task[task_id].running_time
    #
    #             heft_rank[task_id] = score
    #
    #             return score
    #
    #     for id in self.succ_task_for_ids:
    #         CalculateRankForEach(id)
    #
    #     result = sorted(heft_rank.items(), key=lambda item:item[1], reverse=True)
    #     self.sorted_task = result
    #
    #     return result

    # def _parse_dependency_by_ids(self):
    #     children = self.collection.getElementsByTagName("child")
    #     dependencies = {}
    #
    #     for child in children:
    #         child_id = child.getAttribute("ref")
    #         parents = child.getElementsByTagName("parent")
    #
    #
    #         for parent in parents:
    #             parent_id = parent.getAttribute("ref")
    #
    #             self.pre_task_for_ids[child_id].append(parent_id)
    #             self.succ_task_for_ids[parent_id] += [child_id]
    #
    #             comunicate_delay = self.ids_to_output_size[parent_id] / (1000.0 * 1024.0 * 1024.0 / 8.0)
    #
    #             dependencies[(parent_id, child_id)] = comunicate_delay
    #
    #     return dependencies


    # def _calculate_depth(self):
    #     ids_to_depth = dict()
    #
    #     def caluclate_depth_value(id):
    #         if id in ids_to_depth.keys():
    #             return ids_to_depth[id]
    #         else:
    #             if len(self.pre_task_for_ids[id]) != 0:
    #                 depth = 1 + max([caluclate_depth_value(pre_task_id) for
    #                                         pre_task_id in self.pre_task_for_ids[id]])
    #             else:
    #                 depth = 0
    #
    #             ids_to_depth[id] = depth
    #
    #         return ids_to_depth[id]
    #
    #     for id in self.pre_task_for_ids:
    #         ids_to_depth[id] = caluclate_depth_value(id)
    #
    #     return ids_to_depth


    def _sort_task_by_topology(self):
        #sort all task by topology
        pass

# Test basic parse method
if __name__  == "__main__":

    node_parser = BasicParser('./xml/plane_dag.xml')

    print(node_parser.dependencies)
    print("---------------")
    curr_node = node_parser.get_nodes()[2]
    print(curr_node)
    print("-->")
    for parent in curr_node.parent_nodes:
        print(parent)
    #task_parser.parse_task()
    #print(len(task_parser.succ_task_for_ids))
    #dependencies = task_parser.parse_dependency_by_ids()

    #print(task_parser.succ_task_for_ids)

    # print(task_parser.sorted_task)
    # print(task_parser.dependencies)
    #
    # task_list = task_parser.generate_task_list()
    # task_depth = task_parser._calculate_depth()
    #
    # print(task_depth)
    #
    # for i, task in enumerate(task_list):
    #     print("{}: {}".format(i, task.id_name))
    #
    # print(task_parser.pre_task_for_ids)
    # print(task_parser.dependencies[('ID00002', 'ID00003')])

